﻿using ALApps.Graphics.Interface;
using ALApps.Graphics.Interface.Engine;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SunrayEngine.MapEditor.EditTools;
using System;
using SunrayEngine.Maps;

namespace SunrayEngine.MapEditor.Interface.Items
{
    public enum ToolState
    {
        Draw,
        Walk,
        EraseDraw,
        EraseWalk
    }

    public class WorkBench : Item, IDrawableItem
    {
        #region fields
        private Brush brush;
        private EditableMapGrid grid;
        private Texture2D prim;
        private ToolState toolState;
        private bool scrolling;
        private bool painting;
        #endregion

        #region properties
        public EditableMapTile[,] Tiles { get { return grid.Tiles; } }
        public int MapWidth { get; set; }
        public int MapHeight { get; set; }

        public int BrushSize 
        { 
            get { return brush.Size; }
            set { brush.Size = value; }
        }

        public int BrushAlpha
        {
            get { return brush.Alpha; }
            set { brush.Alpha = value; }
        }

        public Texture2D IniTileTexture { get; set; }

        public Texture2D BrushTexture
        {
            get { return brush.Texture; }
            set { brush.Texture = value; }
        }

        public Color BrushColor
        {
            get { return brush.Color; }
            set { brush.Color = value; }
        }

        public Color Color { get; set; }

        public string Tooltip { get; set; }

        public object Tag { get; set; }
        #endregion

        #region initialization
        public WorkBench()
        {
            toolState = ToolState.Draw;

            brush = new Brush();

            OnFocused += (s, e) => { brush.Active = true; };
            OnLostFocus += (s, e) => { brush.Active = false; };

            brush.Active = false;

            prim = InterfaceEngine.Scripting.Execute("Textures['prim']");

            OnMouseMiddleClicked += (s, e) => { scrolling = true; };
            OnMouseMiddleReleased += (s, e) => { scrolling = false; };

            OnMouseRightClicked += (s, e) =>
            {
                painting = true;
                if (toolState == ToolState.Draw)
                    toolState = ToolState.EraseDraw;

                if (toolState == ToolState.Walk)
                    toolState = ToolState.EraseWalk;
            };

            OnMouseRightReleased += (s, e) =>
            {
                painting = false;
                if (toolState == ToolState.EraseDraw)
                    toolState = ToolState.Draw;

                if (toolState == ToolState.EraseWalk)
                    toolState = ToolState.Walk;
            };

            OnMouseLeftClicked += (s, e) => { painting = true; };
            OnMouseLeftReleased += (s, e) => { painting = false; };
            OnLostFocus += (s, e) => 
            {
                painting = false;
                scrolling = false;

                if (toolState == ToolState.EraseDraw)
                    toolState = ToolState.Draw;

                if (toolState == ToolState.EraseWalk)
                    toolState = ToolState.Walk;
            };
        }

        public override void Initialize()
        {
            base.Initialize();

            grid = new EditableMapGrid(X, Y, MapWidth, MapHeight, InterfaceEngine.Scripting.Execute("GraphicsDevice"), Bounds);
            if (IniTileTexture != null)
            {
                SetFromTexture(IniTileTexture);
            }
        }

        protected override void calculateBounds()
        {
            base.calculateBounds();

            if(grid != null)
                grid.UpdateTilesOnScreen(Bounds);
        }
        #endregion

        #region methods
        public void SetTiles(MapTile[,] tiles)
        {
            for(int x = 0; x < tiles.GetLength(0); x++)
                for(int y = 0; y < tiles.GetLength(1); y++)
                    grid.Tiles[x, y].EditInfo(tiles[x, y].Pixels);
        }

        public PixelInfo[,] GetPixelInfo()
        {
            return grid.GetPixelInfo();
        }

        public void SetTool(string str)
        {
            toolState = (ToolState)Enum.Parse(typeof(ToolState), str);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(prim, Bounds, Color);

            grid.Draw(spriteBatch);

            if (toolState == ToolState.EraseWalk || toolState == ToolState.Walk)
                grid.DrawWalkabel(spriteBatch);

            brush.Draw(spriteBatch);
        }

        public override void Update()
        {
            base.Update();

            if (painting)
            {
                switch (toolState)
                {
                    case ToolState.Draw:
                        paint(false);
                        break;

                    case ToolState.Walk:
                        walkPaint(false);
                        break;

                    case ToolState.EraseDraw:
                        paint(true);
                        break;

                    case ToolState.EraseWalk:
                        walkPaint(true);
                        break;
                }
            }

            if (scrolling)
            {
                scroll();
                grid.UpdateTilesOnScreen(Bounds);
            }
        }

        protected void SetFromTexture(Texture2D texture)
        {
            for (int x = 0; x < grid.Tiles.GetLength(0); x++)
                for (int y = 0; y < grid.Tiles.GetLength(1); y++)
                    grid.Tiles[y, x].SetPixelsFromTexture(IniTileTexture);
        }

        private void walkPaint(bool erase)
        {
            foreach(var p in grid.TilesOnScreen)
                if (grid.Tiles[p.Y, p.X].Bounds.Intersects(brush.GetBounds()))
                    grid.Tiles[p.Y, p.X].SetWalkabels(brush, erase);
        }

        private void paint(bool erase)
        {
            foreach (var p in grid.TilesOnScreen)
                if (grid.Tiles[p.Y, p.X].Bounds.Intersects(brush.GetBounds()))
                    grid.Tiles[p.Y, p.X].PaintToTile(brush, erase);
        }

        private void scroll()
        {
            Vector2 mDelta = InterfaceEngine.Input.MouseDelta;
            Point p = new Point((int)mDelta.X, (int)mDelta.Y);
            grid.EditOffset(p);
        }
        #endregion
    }
}
